//
//  ViewController.m
//  CodeForGCD
//
//  Created by relax on 2017/10/5.
//  Copyright © 2017年 relax. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

#pragma mark 系统主队列异步执行
- (IBAction)systemMainQueue:(id)sender {

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@ %@",@"我是主线程任务1",
              [NSThread currentThread]
              );
    });

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@ %@",@"我是主线程任务2",
              [NSThread currentThread]
              );
    });

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"%@ %@",@"我是主线程任务3 ,前面肯定要等 1，2执行完毕，才能到我，而且我们三个全在主线程",
              [NSThread currentThread]
              );
    });

    /*
     特点，主线程异步，在主线程按照任务顺序串行执行。并且，只能等待主线程闲置的时候，才能执行。这里的异步是假异步，
     更多的可能是为了标记，这些任务必须等待主线程闲置的时候才能执行。
     */
}

#pragma mark 系统主队列死锁
- (IBAction)systemMainQueueDieLock:(id)sender {
    dispatch_sync(dispatch_get_main_queue(), ^{
        //
        NSLog(@"%@ %@",[NSThread currentThread],@"我是排主线程的同步任务。这样是不行的。因为我插队了~");
    });

    /*
     解释为什么报错：
     因为，在 dispatch_get_main_queue()队列中的任务肯定是在主线程中完成的。且必须等待主线程闲置。
     如果在主线队列，添加一个同步任务，那么主线程无法执行完毕。同步任务，又要等待主线程执行完毕，才能执行自己。于是就出现了死锁。
     */
}

#pragma mark 系统并行队列同步执行
- (IBAction)systemCurrentQueueSync:(id)sender {

    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@ %@",@"我是并行任务同步执行 1",
              [NSThread currentThread]
              );

    });

    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@ %@",@"我是并行任务同步执行 2",
              [NSThread currentThread]
              );

    });
    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@ %@",@"我是并行任务同步执行 3",
              [NSThread currentThread]
              );

    });

    dispatch_sync(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@ %@",@"我是并行任务同步执行 4,前面有1，2，3个任务执行完毕之后才能到后，好像并没有并行的执行我们4个任务",
              [NSThread currentThread]
              );

    });

    /*
     队列是并行的，仅仅只是表明队列里的任务有并行的能力。到底能不能并行，还要看搭配队列的执行方式是同步的还是异步的。
     如果是同步执行，不开启子线程的话，那么并行队列的任务会在当前线程（不是 UI 主线程）按照串行队列的方式串行执行。
     */
}

#pragma mark 系统并行队列异步执行
- (IBAction)systemCurrentQueueAsync:(id)sender {

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@ %@",@"我是并行任务异步执行1",
              [NSThread currentThread]
              );

    });

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@ %@",@"我是并行任务异步执行2",
              [NSThread currentThread]
              );

    });

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@ %@",@"我是并行任务异步执行3",
              [NSThread currentThread]
              );

    });

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSLog(@"%@ %@",@"我是并行任务异步执行4,我们兄弟4人执行顺序不确定啊，我也不知道谁会先执行完毕。",
              [NSThread currentThread]
              );

    });


}

#pragma mark 自定义串行队列同步执行
- (IBAction)selfSerialQueueSync:(id)sender {
    dispatch_queue_t selfSerialQueue = dispatch_queue_create("自定义串行队列",
                                                             DISPATCH_QUEUE_SERIAL
                                                             );
    dispatch_sync(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列哦，我可以在当前线程(即使是 UI 主线程)也能同步执行哦，不必等 UI 线程闲置哦 111",
              [NSThread currentThread]
              );

    });

    dispatch_sync(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列哦，我可以在当前线程(即使是 UI 主线程)也能同步执行哦，不必等 UI 线程闲置哦 222",
              [NSThread currentThread]
              );

    });

    dispatch_sync(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列哦，我可以在当前线程(即使是 UI 主线程)也能同步执行哦，不必等 UI 线程闲置哦 333",
              [NSThread currentThread]
              );

    });

    dispatch_sync(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列哦，我可以在当前线程(即使是 UI 主线程)也能同步执行哦，不必等 UI 线程闲置哦 444,",
              [NSThread currentThread]
              );
    });

    dispatch_sync(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列哦，我前面1，2，3，4兄弟都执行完毕了，才能到我!",
              [NSThread currentThread]
              );

    });

    /*
     自定义串行队列可以在 UI 主线程同步执行，而不必等待 UI 主线程闲置。这一点是和系统主线程最大的区别。
     自定义串行的同步和异步本质上是在当前执行做任务，还是开启一个新的线程做任务。
     和任务执行的模式无关。都是按照顺序一个接着一个的执行。仅此而已。
     */
}

#pragma mark 自定义串行队列异步执行
- (IBAction)selfSerialQueueAsync:(id)sender {
    // 1. 自定义行队列
    dispatch_queue_t selfSerialQueue = dispatch_queue_create("自定义串行队列",
                                                             DISPATCH_QUEUE_SERIAL
                                                             );

    dispatch_async(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列异步执行哦~~ 111",
              [NSThread currentThread]
              );

    });

    dispatch_async(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列异步执行哦~~ 222",
              [NSThread currentThread]
              );

    });

    dispatch_async(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列异步执行哦~~ 333",
              [NSThread currentThread]
              );

    });

    dispatch_async(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是自定义串行队列异步执行哦~~ 444",
              [NSThread currentThread]
              );

    });

    dispatch_async(selfSerialQueue, ^{
        NSLog(@"%@ %@",@"我是5 ，我必须等前面1，2，3，4它们四个兄弟执行完毕之后，才到我。虽然是异步的，但仅仅只是开了个新线程而已，执行的任务的过程耗时线性的。",
              [NSThread currentThread]
              );

    });


    /*
     对于自定义串行队列异步执行来说，仅仅是开启了一个新的线程串行的执行任务，任务执行的顺序没变，还是按照顺序一个一个的执行。仅仅是开了一个新的线程而已。
     对于主队列异步来说，自定义的串行异步可以开启信息线程，而主队列开异步，没有开启新线程，仍然是在主线程执行，且必须等待主线程闲置的时候。
     */

}

#pragma mark 自定义并行队列，同步执行
- (IBAction)selfConcurrentQueueSync:(id)sender {
    // 1. 创建自定义并行队列
    dispatch_queue_t selfConCurrentQueue = dispatch_queue_create("自定义并行队列", DISPATCH_QUEUE_CONCURRENT);

    // 2. 让并行队列任务丧失并行能力，在当前线程同步执行。
    dispatch_sync(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是自定义并行队列同步执行的任务 1111",
              [NSThread currentThread]
              );
    });

    dispatch_sync(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是自定义并行队列同步执行的任务 2222",
              [NSThread currentThread]
              );
    });

    dispatch_sync(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是自定义并行队列同步执行的任务 3333",
              [NSThread currentThread]
              );
    });

    dispatch_sync(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是自定义并行队列同步执行的任务 4444",
              [NSThread currentThread]
              );
    });

    dispatch_sync(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是5，虽然是在一个并行队列，但是同步执行了，我必须等待 1,2,3,4 四个兄弟执行完毕之后才能到我，并且我们5兄弟之分到了一个线程资源，就是当前线程。",
              [NSThread currentThread]
              );
    });



    /*
     自定义并行队列和系统提供的并行队列，起码在使用上没有任何区别。
     并行队列仅仅表示这个队列里的任务拥有并行的能力，到底能不能并行执行，还要看和当前队列搭配的调度模式是同步还是异步。
     同步，此并行队列就丧失了并行的能力，仅仅只能在当前线程(不一定是 UI 主线程）串行的执行并行队列里的任务。
     */
    
}

#pragma mark 自定义并行队列，异步执行
- (IBAction)selfConcurrentQueueAsync:(id)sender {
    // 1. 创建自定义并行队列
    dispatch_queue_t selfConCurrentQueue = dispatch_queue_create("自定义并行队列", DISPATCH_QUEUE_CONCURRENT);

    // 2. 让并行队列搭配异步执行，完全发挥出并行队列任务并行的强大威力
    dispatch_async(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是并行异步执行队列中的任务 111",
              [NSThread currentThread]
              );
    });

    dispatch_async(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是并行异步执行队列中的任务 222",
              [NSThread currentThread]
              );
    });

    dispatch_async(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是并行异步执行队列中的任务 333",
              [NSThread currentThread]
              );
    });

    dispatch_async(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是并行异步执行队列中的任务 444",
              [NSThread currentThread]
              );
    });

    dispatch_async(selfConCurrentQueue, ^{
        NSLog(@"%@ %@",@"我是555，最后一个加入到并行队列的异步任务，但我并不一定是最后一个执行完毕的，线程的调度完全看 CPU 的心情，也许我是最后一个分配到线程的，但有可能是第一个执行完毕的呢？谁叫 cpu 爱我呢！！没办法",
              [NSThread currentThread]
              );
    });


}












@end
